/*********************************************************************************
 * Software License Agreement (BSD License)
 * Copyright (c) 2012, Carlos D. Correa (info@ngraph.org)
 *               2011, Nick Leaf (UC Davis)
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of netzen nor the
 *    names of its contributors may be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************************/
#ifndef FM3LAYOUT_H
#define FM3LAYOUT_H

#include "GPULayout-lite_cus02/GM3Graph.h"
#include "GPULayout-lite_cus02/GPULayout.h"


#include "layout.h"
#include "ui/uiUtils.h"
#include "graph.h"

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
//#include <assert.h>

// Nick's FM3
//#include "GPULayout-lite_cus02/GM3Graph.h";
//#include "layouts/GPULayout-lite_cus02/cvec.h"
//#include "layouts/GPULayout-lite_cus02/GM3Graph.h"
//#include "layouts/GPULayout-lite_cus02/GM3Layout.h"
//#include "layouts/GPULayout-lite_cus02/GPULayout.h"
////#include "layouts/GPULayout-lite_cus02/KDTree.h"
//#include "layouts/GPULayout-lite_cus02/oclUtil.h"
//#include "layouts/GPULayout-lite_cus02/svec.h"

////#include "GPULayout-lite_cus02/GM3Layout.h";
////#include "GPULayout-lite_cus02/GPULayout.h";


class GPULayout;
class GM3Graph::node;
class GM3Graph::edge;

using namespace std;

//class GM3Layout;

class FM3Layout:public Layout, TimerListener {
protected:
private:




//    float timestep;
//    float K;
//    float T;
//    float repulsion;

    bool running;
    vector<int> visible; //indexes of visible nodes in layout.
    Timer *timer;








    int numEdges(){
        return graph->numEdges;
    }






public:
    FM3Layout(const char *name);
    virtual void update(string property);

    bool isRunning();
    void setRunning(bool value);


    virtual int numNodes() {
        return graph->nodes.size();
    }
    virtual bool isNodeInLayout(int i){
        return this->getNode(i)->isVisible();
    }
    virtual bool isEdgeInLayout(int i, int j){
        bool ifNodeI = this->isNodeInLayout(i);
        bool ifNodeJ = this->isNodeInLayout(j);
        return (ifNodeI && ifNodeJ);
    }
    float randomFM3(float a, float b) {
        return a + (b-a)*(float) rand()/(float) RAND_MAX;
    }


    Node* getNode(int i){
        return graph->nodes[i];
    }


    virtual int numNeighbors(int i){
        return this->getNode(i)->edges.size();
    }
    virtual int getNeighborIndex(int i, int egk){
        int neighborIdx = this->getNode(i)->edges[egk]->getNode1()->getIndex();
        return neighborIdx;
    }
    void updateVisible();
    void computeIteration(bool ifPrintMsg);
    void reset();
    void compute();


    virtual void timerEvent();

    // =====================================

    //Nick's
    GPULayout *gpulayout;
    vector< GM3Graph::edge > fm3edges;
    vector< GM3Graph::node > fm3nodes;
    map<int,int> mapIDtoNEWID;
    map<int,int> mapIDtoNEWID_previous;
    map<int,int> mapNEWIDtoID;
    map<int,int>::iterator itr;
    int maxN, maxE; //max number of nodes and edges, for initializing GPU memory.
    void setupFM3parameters();
    bool setupGPU_node_edge();
    bool setNodeAfterLayout_withGraph(GM3Graph *g);
    bool setNodeIniPos();
    bool updateNodePosNow();
    //bool setupGraphToGPU();

    map<int, map<int, int> > mapEdgeSaved; // map<fromNodeID, map<toNodeID, multiplicityTime>
    map<int, map<int, int> >::iterator itrFromNode;
    map<int,int>::iterator itrToooNode;


//    void load();
//    void save();
    //bool getLocation(int t, int nodeID, float &x, float &y);
    //bool setLocation(int t, int nodeID, float x, float y);




};

Layout *createFM3Layout(string name);


#endif // FM3LAYOUT_H
